package cz.muni.fi.pb138.odsKartW;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jopendocument.dom.spreadsheet.Sheet;
import org.jopendocument.dom.spreadsheet.SpreadSheet;

/**
 * 
 * @author Michal Sorentiny
 * @version 05/05/2011
 */
public class MediaManagerImpl implements MediaManager {

    private SpreadSheet spreadSheet;
    private File file;
    
    public MediaManagerImpl(File file) throws IOException{
        spreadSheet =  SpreadSheet.createFromFile(file);
        this.file = file;
    }
    
    @Override
    public void createMedium(Medium medium) throws ODSKartWException {
        Sheet sheet = spreadSheet.getSheet(medium.getSheetLabel());
        
        if (sheet == null) throw new ODSKartWException("Medium je z neznámej záložky.");

        //It can not be posible add medium with same titles
        if (sameMediumPresent(medium)) throw new ODSKartWException("Medium s rovnakým názvom už existuje!!!");
        
        if (sheet.getColumnCount() <= medium.getTitles().size()){
            throw new ODSKartWException("Medium contains too much titles!!!");
        }
        boolean empty = true;
        for (Title t:medium.getTitles()){
            if (!t.getName().equals("")) empty=false;
        }
        if (empty)throw new ODSKartWException("Vyplň aspoň 1 názov!!!");
        //increaing rowcount
        sheet.setRowCount(sheet.getRowCount()+1);
        //First two cells are in every sheet (ID, label)
        sheet.getCellAt(0,sheet.getRowCount()-1).setValue(sheet.getRowCount()-1);
        
        for (int i=0;i<medium.getTitles().size();i++){
            sheet.getCellAt(i+1,sheet.getRowCount()-1).setValue(medium.getTitles().get(i).getName());
        }
       
        try {
            //we save content in file
            spreadSheet.saveAs(file);
        } catch (IOException ex) {
            Logger.getLogger(MediaManagerImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new ODSKartWException("IOException: "+ex.getMessage());
        }
    }

    
    @Override
    public void updateMedium(Medium medium) throws ODSKartWException {
        
        if (medium == null) throw new NullPointerException("Medium null pointer");
        if (medium.getSheetLabel() == null) throw new NullPointerException("sheetLabel null pointer");
        Sheet sheet = spreadSheet.getSheet(medium.getSheetLabel());
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        int ID = medium.getID();
        if (ID<1 || ID>=sheet.getRowCount()) throw new ODSKartWException("Unknown ID");
        if (sheet.getColumnCount() <= medium.getTitles().size()){
            throw new ODSKartWException("Medium contains too much titles!!!");
        }
        //It can not be posible add medium with same titles
        if (sameMediumPresent(medium)) throw new ODSKartWException("Medium s rovnakým názvom už existuje!!!");
        
        boolean empty = true;
        for (Title t:medium.getTitles()){
            if (!t.getName().equals("")) empty=false;
        }
        if (empty)throw new ODSKartWException("Vyplň aspoň 1 položku!!!");
        
        for (int i=0;i<medium.getTitles().size();i++){
             sheet.getCellAt(i+1,ID).setValue(medium.getTitles().get(i).getName());
        }
         try {
            //we save content in file
            spreadSheet.saveAs(file);
        } catch (IOException ex) {
            Logger.getLogger(MediaManagerImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

   
    @Override
    public List<String> getHeader(String sheetLabel) throws ODSKartWException{
        if(sheetLabel == null){
            throw new NullPointerException("SheetLabel null pointer");
        }
        Sheet sheet = spreadSheet.getSheet(sheetLabel);
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        
        List<String> media = new ArrayList<String>();
        for (int i = 0; i<sheet.getColumnCount();i++){
            String HeaderOfColumn = sheet.getCellAt(i, 0).getTextValue();
            if (HeaderOfColumn.isEmpty()) {
                //in this case column count is bigger then header, then we fix it and return
                sheet.setColumnCount(i); 
                return media;
            }   
            media.add(HeaderOfColumn);              
        }
        return media;
    }

   
    @Override
    public List<Medium> findAllMedia(String sheetLabel)throws ODSKartWException{
        if(sheetLabel == null){
            throw new NullPointerException("SheetLabel null pointer");
        }
        Sheet sheet = spreadSheet.getSheet(sheetLabel);
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        List<Medium> media = new ArrayList<Medium>();
        for(int i = 1;i<sheet.getRowCount();i++){
            Medium medium = new Medium(i);
            medium.setSheetLabel(sheetLabel);
            if (sheet.getColumnCount()>1) {
                for (int j=1;j<sheet.getColumnCount();j++){
                    String titleLabel = sheet.getCellAt(j, i).getTextValue();

                    Title title = new Title(titleLabel);
                    medium.getTitles().add(title);
                    
                }
            }
            media.add(medium);
        }
        return media;
        
    }

    @Override
    public void deleteMediumAccordingIdAndSheetLabel(int ID, String sheetLabel) throws ODSKartWException {
        if (sheetLabel == null) throw new NullPointerException("sheetLabel null pointer");
        Sheet sheet = spreadSheet.getSheet(sheetLabel);
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        if (ID<1 || ID>=sheet.getRowCount()) throw new ODSKartWException("Unknown ID");
        
        for (int i=0; i+1<sheet.getColumnCount();i++){
            sheet.getCellAt(i+1,ID).setValue(sheet.getCellAt(i+1,sheet.getRowCount()-1 ).getTextValue());
        }
        sheet.setRowCount(sheet.getRowCount()-1);
        
        try {
            //we save content in file
            spreadSheet.saveAs(file);
        } catch (IOException ex) {
            Logger.getLogger(MediaManagerImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public List<Medium> getMediums(String title) throws ODSKartWException {
        if (title == null) throw new NullPointerException("title null pointer");
        List<Medium> array= new ArrayList<Medium>();
        for (int n=0; n<spreadSheet.getSheetCount();n++){
            array.addAll(getMediums(spreadSheet.getSheet(n).getName(),title));
        }
        return array;
    }

    @Override
    public List<Medium> getMediums(String sheetLabel, String title, int columnNumber) throws ODSKartWException {
        if (sheetLabel == null) throw new NullPointerException("sheetLabel null pointer");
        if (title == null) throw new NullPointerException("title null pointer");
        Sheet sheet = spreadSheet.getSheet(sheetLabel);
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        if (columnNumber<1 || columnNumber>=sheet.getColumnCount()) throw new ODSKartWException("Unknown ID");
        List<Medium> array= new ArrayList<Medium>();
        for (int i=1; i<sheet.getRowCount();i++){
            //if (sheet.getCellAt(columnNumber, i).getTextValue().equals(title)){
            if (sheet.getCellAt(columnNumber, i).getTextValue().toLowerCase().contains(title.toLowerCase())){
                Medium medium = new Medium(i);
                medium.setSheetLabel(sheetLabel);
                for (int j=1;j<sheet.getColumnCount();j++){
                    medium.getTitles().add(new Title(sheet.getCellAt(j, i).getTextValue()));
                }
                array.add(medium);
            }
        }
        return array;
    }

    @Override
    public List<Medium> getMediums(String sheetLabel, String title) throws ODSKartWException {
        if (sheetLabel == null) throw new NullPointerException("sheetLabel null pointer");
        if (title == null) throw new NullPointerException("title null pointer");
        Sheet sheet = spreadSheet.getSheet(sheetLabel);
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        List<Medium> array = new ArrayList<Medium>();
        for (int k=1; k<sheet.getColumnCount();k++){
            List<Medium> pom = getMediums(sheetLabel,title,k);
            for(Medium medium:pom){
                if (!array.contains(medium)) array.add(medium);
            }
            
        }
        return array;
    }

    @Override
    public boolean sameMediumPresent(Medium medium) throws ODSKartWException {
        if (medium == null) throw new NullPointerException("Medium null pointer");
        if (medium.getSheetLabel() == null) throw new NullPointerException("sheetLabel null pointer");
        Sheet sheet = spreadSheet.getSheet(medium.getSheetLabel());
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        if (medium.getTitles().size() >= sheet.getColumnCount()) return false;
        
        for(int i= 1;i<sheet.getRowCount();i++){
            if (medium.getTitles().get(0).getName().equals(sheet.getCellAt(1, i).getTextValue())){
                for (int j=2;j<sheet.getColumnCount();j++){
                    if (!medium.getTitles().get(j-1).getName().equals(sheet.getCellAt(j,i).getTextValue())){
                        break;
                    }
                    else if(j+1 == sheet.getColumnCount()){
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    public List<String> getSheetLabels() throws ODSKartWException {
        List<String> sheetLabels = new ArrayList<String>();
        for (int i = 0; i<spreadSheet.getSheetCount();i++){ 
            sheetLabels.add(spreadSheet.getSheet(i).getName());              
        }
        return sheetLabels;
    }

    @Override
    public Medium getMediumAccordingIdAndSheetLabel(int ID, String sheetLabel) throws ODSKartWException {
        if (sheetLabel == null) throw new NullPointerException("sheetLabel null pointer");
        Sheet sheet = spreadSheet.getSheet(sheetLabel);
        if (sheet == null)  throw new ODSKartWException("Unknown SheetLabel");
        if (ID<1 || ID>=sheet.getRowCount()) throw new ODSKartWException("Unknown ID");
        
        Medium medium = new Medium(sheetLabel);
        medium.setID(ID);
        List<Title> titles = new ArrayList<Title>();
        for (int i=1; i<sheet.getColumnCount();i++){
            titles.add(new Title(sheet.getCellAt(i,ID).getTextValue()));
        }
       medium.setTitles(titles);
        return medium;
    }
    
}
